/*
Pointers:  Classes for manage memory space.
    Copyright (C) 2012  Jorge E. A. Atala
                        FuDePAN
    This file is part of the Fui Proyect.

    Fui is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Fui is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Fui.  If not, see <http://www.gnu.org/licenses/>.
*/


#ifndef POINTERS_H
#   define POINTERS_H
namespace fui
{
template<class T>
class device_ptr
{
    typedef T* Raw_Pointer;
    Raw_Pointer ptr;
public:
    inline device_ptr(const device_ptr<T>& other)
        :   ptr(other->ptr)
    {}

    device_ptr<T>& operator= (const device_ptr<T>& other)
    {
        this->ptr = other.ptr;
        return *this;
    }

    T operator*(void) const
    {
        return *ptr;
    }


    Raw_Pointer get(void) const
    {
        return ptr;
    }
};

template<class T>
class device_reference
{
    typedef T& Raw_Reference;

    Raw_Reference reference;
public:
    inline device_reference(const device_reference<T>& other)
        :   reference(other->reference)
    {}

    inline device_reference(const device_ptr<T>& ptr)
        :   reference(*(ptr.get()))
    {}


    device_reference<T>& operator= (const device_reference<T>& other)
    {
        this->reference = other.reference;
        return *this;
    }

    device_reference<T>& operator= (const T& x)
    {
        this->reference = x;
        return this;
    }

    device_ptr<T> operator&(void) const
    {
        return device_ptr<T>(reference);
    }

    operator T(void) const
    {
        return reference;
    }

    void swap(device_reference<T>& other)
    {
        T aux = other.reference;
        other.reference = this->reference;
        this->reference = aux;
    }

    device_reference<T>& operator++(void)
    {
        ++reference;
        return *this;
    }

    T operator++(int)
    {
        return reference++;
    }

    device_reference<T>& operator+= (const T& other)
    {
        reference += other;
        return *this;
    }

    device_reference<T>& operator--(void)
    {
        --reference;
        return *this;
    }

    T operator--(int)
    {
        return reference--;
    }

    device_reference<T>& operator-= (const T& other)
    {
        reference -= other;
        return *this;
    }

    device_reference<T>& operator*= (const T& other)
    {
        reference *= other;
        return *this;
    }

    device_reference<T>& operator/= (const T& other)
    {
        reference /= other;
        return *this;
    }

    device_reference<T>& operator%= (const T& other)
    {
        reference %= other;
        return *this;
    }

    device_reference<T>& operator<<= (const T& other)
    {
        reference <<= other;
        return *this;
    }

    device_reference<T>& operator>>= (const T& other)
    {
        reference >>= other;
        return *this;
    }

    device_reference<T>& operator&= (const T& other)
    {
        reference &= other;
        return *this;
    }

    device_reference<T>& operator|= (const T& other)
    {
        reference |= other;
        return *this;
    }

    device_reference<T>& operator^= (const T& other)
    {
        reference ^= other;
        return *this;
    }

};

}
#endif


